home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / andere sprachen / oberonv4 / oberon-src / system / oberon.mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1996-04-09  |  15.9 KB  |  497 lines

  1. Syntax20b.Scn.Fnt
  2. ParcElems
  3. Alloc
  4. Syntax24b.Scn.Fnt
  5. Syntax10.Scn.Fnt
  6. Syntax10i.Scn.Fnt
  7. Syntax10b.Scn.Fnt
  8. (* AMIGA *)
  9. MODULE Oberon; (*JG 6.9.90*)    (* << RC 19.3.93, shml, cn 2.6.94 *)
  10.     IMPORT SYSTEM, Amiga, AmigaDos, Kernel, Modules, Input, Display, Fonts, Viewers, Texts, V24;
  11.     CONST
  12.         (*message ids*)
  13.         consume* = 0; track* = 1; (* InputMsg *)
  14.         defocus* = 0; neutralize* = 1; mark* = 2; (* ControlMsg *)
  15.         BasicCycle = 20;
  16.         ESC = 1BX; SETUP = 0A4X;
  17.     TYPE
  18.         Painter* = PROCEDURE (x, y: INTEGER);
  19.         Marker* = RECORD Fade*, Draw*: Painter END;
  20.         Cursor* = RECORD
  21.             marker*: Marker; on*: BOOLEAN; X*, Y*: INTEGER
  22.         END;
  23.         ParList* = POINTER TO ParRec;
  24.         ParRec* = RECORD
  25.             vwr*: Viewers.Viewer;
  26.             frame*: Display.Frame;
  27.             text*: Texts.Text;
  28.             pos*: LONGINT
  29.         END;
  30.         InputMsg* = RECORD (Display.FrameMsg)
  31.             id*: INTEGER;
  32.             keys*: SET;
  33.             X*, Y*: INTEGER;
  34.             ch*: CHAR;
  35.             fnt*: Fonts.Font;
  36.             col*, voff*: SHORTINT
  37.         END;
  38.         SelectionMsg* = RECORD (Display.FrameMsg)
  39.             time*: LONGINT;
  40.             text*: Texts.Text;
  41.             beg*, end*: LONGINT
  42.         END;
  43.         ControlMsg* = RECORD (Display.FrameMsg)
  44.             id*, X*, Y*: INTEGER
  45.         END;
  46.         CopyOverMsg* = RECORD (Display.FrameMsg)
  47.             text*: Texts.Text;
  48.             beg*, end*: LONGINT
  49.         END;
  50.         CopyMsg* = RECORD (Display.FrameMsg)
  51.             F*: Display.Frame
  52.         END;
  53.         Task* = POINTER TO TaskDesc;
  54.         Handler* = PROCEDURE;
  55.         TaskDesc* = RECORD
  56.             next: Task;
  57.             safe*: BOOLEAN;
  58.             time*: LONGINT;
  59.             handle*: Handler
  60.         END;
  61.         User*: ARRAY 8 OF CHAR;
  62.         Password*: LONGINT;
  63.         Arrow*, Star*: Marker;
  64.         Mouse*, Pointer*: Cursor;
  65.         FocusViewer*: Viewers.Viewer;
  66.         Log*: Texts.Text;
  67.         Par*: ParList; (*actual parameters*)
  68.         CurTask*, PrevTask: Task;
  69.         CurFnt*: Fonts.Font; CurCol*, CurOff*: SHORTINT;
  70.         DW, DH, CL, H0, H1, H2, H3: INTEGER;
  71.         unitW: INTEGER;
  72.         ActCnt: INTEGER; (*action count for GC*)
  73.         Mod: Modules.Module;
  74.     (*user identification*)
  75.     PROCEDURE Code(VAR s: ARRAY OF CHAR): LONGINT;
  76.         VAR i: INTEGER; a, b, c: LONGINT;
  77.     BEGIN
  78.         a := 0; b := 0; i := 0;
  79.         WHILE s[i] # 0X DO
  80.             c := b; b := a; a := (c MOD 509 + 1) * 127 + ORD(s[i]);
  81.             INC(i)
  82.         END;
  83.         IF b >= 32768 THEN b := b - 65536 END;
  84.         RETURN b * 65536 + a
  85.     END Code;
  86.     PROCEDURE SetUser* (VAR user, password: ARRAY OF CHAR);
  87.     BEGIN COPY(user, User); Password := Code(password)
  88.     END SetUser;
  89.     (*clocks*)
  90.     PROCEDURE GetClock* (VAR t, d: LONGINT);
  91.     BEGIN Kernel.GetClock(t, d)
  92.     END GetClock;
  93.     PROCEDURE SetClock* (t, d: LONGINT);
  94.     BEGIN Kernel.SetClock(t, d)
  95.     END SetClock;
  96.     PROCEDURE Time* (): LONGINT;
  97.     BEGIN RETURN Input.Time()
  98.     END Time;
  99.     (*cursor handling*)
  100.     PROCEDURE FlipArrow (X, Y: INTEGER);
  101.     BEGIN
  102.         (*IF X < CL THEN *)
  103.             (*IF X > DW - 15 THEN X := DW - 15 END *)
  104.         (*ELSE *)
  105.             (*IF X > CL + DW - 15 THEN X := CL + DW - 15 END *)
  106.         (*END; *)
  107.         (*IF Y < 14 THEN Y := 14 ELSIF Y > DH THEN Y := DH END; *)
  108.         IF X < CL THEN X := CL ELSIF X > CL + DW-1 THEN X := CL + DW-1 END;
  109.         IF Y < 0 THEN Y := 0 ELSIF Y > DH THEN Y := DH END;
  110.         Display.CopyPattern(Display.white, Display.arrow, X, Y - 14, 2)
  111.     END FlipArrow;
  112.     PROCEDURE FlipStar (X, Y: INTEGER);
  113.     BEGIN
  114.         IF X < CL THEN
  115.             IF X < 7 THEN X := 7 ELSIF X > DW - 8 THEN X := DW - 8 END
  116.         ELSE
  117.             IF X < CL + 7 THEN X := CL + 7 ELSIF X > CL + DW - 8 THEN X := CL + DW - 8 END
  118.         END ;
  119.         IF Y < 7 THEN Y := 7 ELSIF Y > DH - 8 THEN Y := DH - 8 END;
  120.         Display.CopyPattern(Display.white, Display.star, X - 7, Y - 7, 2)
  121.     END FlipStar;
  122.     PROCEDURE OpenCursor* (VAR c: Cursor);
  123.     BEGIN c.on := FALSE; c.X := 0; c.Y := 0
  124.     END OpenCursor;
  125.     PROCEDURE FadeCursor* (VAR c: Cursor);
  126.     BEGIN IF c.on THEN c.marker.Fade(c.X, c.Y); c.on := FALSE END
  127.     END FadeCursor;
  128.     PROCEDURE DrawCursor* (VAR c: Cursor; VAR m: Marker; X, Y: INTEGER);
  129.     BEGIN
  130.         IF c.on & ((X # c.X) OR (Y # c.Y) OR (m.Draw # c.marker.Draw)) THEN
  131.             c.marker.Fade(c.X, c.Y); c.on := FALSE
  132.         END;
  133.         IF ~c.on THEN
  134.             m.Draw(X, Y); c.marker := m; c.X := X; c.Y := Y; c.on := TRUE
  135.         END
  136.     END DrawCursor;
  137.     (*display management*)
  138.     PROCEDURE RemoveMarks* (X, Y, W, H: INTEGER);
  139.     BEGIN
  140.         IF (Mouse.X > X - 16) & (Mouse.X < X + W + 16) & (Mouse.Y > Y - 16) & (Mouse.Y < Y + H + 16) THEN
  141.             FadeCursor(Mouse)
  142.         END;
  143.         IF (Pointer.X > X - 8) & (Pointer.X < X + W + 8) & (Pointer.Y > Y - 8) & (Pointer.Y < Y + H + 8) THEN
  144.             FadeCursor(Pointer)
  145.         END
  146.     END RemoveMarks;
  147.     PROCEDURE HandleFiller (V: Display.Frame; VAR M: Display.FrameMsg);
  148.     BEGIN
  149.         WITH V: Viewers.Viewer DO
  150.             IF M IS InputMsg THEN
  151.                 WITH M: InputMsg DO
  152.                     IF M.id = track THEN DrawCursor(Mouse, Arrow, M.X, M.Y) END
  153.                 END
  154.             ELSIF M IS ControlMsg THEN
  155.                  WITH M: ControlMsg DO
  156.                      IF M.id = mark THEN DrawCursor(Pointer, Star, M.X, M.Y) END
  157.                  END
  158.             ELSIF M IS Viewers.ViewerMsg THEN
  159.                 WITH M: Viewers.ViewerMsg DO
  160.                     IF (M.id = Viewers.restore) & (V.W > 0) & (V.H > 0) THEN
  161.                         RemoveMarks(V.X, V.Y, V.W, V.H);
  162.                         Display.ReplConst(Display.black, V.X, V.Y, V.W, V.H, 0)
  163.                     ELSIF (M.id = Viewers.modify) & (M.Y < V.Y) THEN
  164.                         RemoveMarks(V.X, M.Y, V.W, V.Y - M.Y);
  165.                         Display.ReplConst(Display.black, V.X, M.Y, V.W, V.Y - M.Y, 0)
  166.                     END
  167.                 END
  168.             END
  169.         END
  170.     END HandleFiller;
  171.     PROCEDURE OpenDisplay* (UW, SW, H: INTEGER);
  172.         VAR Filler: Viewers.Viewer;
  173.     BEGIN
  174.          Input.SetMouseLimits(Viewers.curW + UW + SW, H);
  175.          Display.ReplConst(Display.black, Viewers.curW, 0, UW + SW, H, 0);
  176.          NEW(Filler); Filler.handle := HandleFiller;
  177.          Viewers.InitTrack(UW, H, Filler); (*init user track*)
  178.          NEW(Filler); Filler.handle := HandleFiller;
  179.          Viewers.InitTrack(SW, H, Filler) (*init system track*)
  180.     END OpenDisplay;
  181.     PROCEDURE DisplayWidth* (X: INTEGER): INTEGER;
  182.     BEGIN RETURN DW
  183.     END DisplayWidth;
  184.     PROCEDURE DisplayHeight* (X: INTEGER): INTEGER;
  185.     BEGIN RETURN DH
  186.     END DisplayHeight;
  187.     PROCEDURE OpenTrack* (X, W: INTEGER);
  188.         VAR Filler: Viewers.Viewer;
  189.     BEGIN
  190.         NEW(Filler); Filler.handle := HandleFiller;
  191.         Viewers.OpenTrack(X, W, Filler)
  192.     END OpenTrack;
  193.     PROCEDURE UserTrack* (X: INTEGER): INTEGER;
  194.     BEGIN RETURN X DIV DW * DW
  195.     END UserTrack;
  196.     PROCEDURE SystemTrack* (X: INTEGER): INTEGER;
  197.     BEGIN RETURN X DIV DW * DW + DW DIV 8 * 5
  198.     END SystemTrack;
  199.     PROCEDURE UY (X: INTEGER): INTEGER;
  200.         VAR fil, bot, alt, max: Display.Frame;
  201.     BEGIN
  202.         Viewers.Locate(X, 0, fil, bot, alt, max);
  203.         IF fil.H >= DH DIV 8 THEN RETURN DH END;
  204.         RETURN max.Y + max.H DIV 2
  205.     END UY;
  206.     PROCEDURE AllocateUserViewer* (DX: INTEGER; VAR X, Y: INTEGER);
  207.     BEGIN
  208.         IF Pointer.on THEN X := Pointer.X; Y := Pointer.Y
  209.         ELSE X := DX DIV DW * DW; Y := UY(X)
  210.         END
  211.     END AllocateUserViewer;
  212.     PROCEDURE SY (X: INTEGER): INTEGER;
  213.         VAR fil, bot, alt, max: Display.Frame;
  214.     BEGIN
  215.         Viewers.Locate(X, DH, fil, bot, alt, max);
  216.         IF fil.H >= DH DIV 8 THEN RETURN DH END;
  217.         IF max.H >= DH - H0 THEN RETURN max.Y + H3 END;
  218.         IF max.H >= H3 - H0 THEN RETURN max.Y + H2 END;
  219.         IF max.H >= H2 - H0 THEN RETURN max.Y + H1 END;
  220.         IF max # bot THEN RETURN max.Y + max.H DIV 2 END;
  221.         IF bot.H >= H1 THEN RETURN bot.H DIV 2 END;
  222.         RETURN alt.Y + alt.H DIV 2
  223.     END SY;
  224.     PROCEDURE AllocateSystemViewer* (DX: INTEGER; VAR X, Y: INTEGER);
  225.     BEGIN
  226.         IF Pointer.on THEN X := Pointer.X; Y := Pointer.Y
  227.         ELSE X := DX DIV DW * DW + DW DIV 8 * 5; Y := SY(X)
  228.         END
  229.     END AllocateSystemViewer;
  230.     PROCEDURE MarkedViewer* (): Viewers.Viewer;
  231.     BEGIN RETURN Viewers.This(Pointer.X, Pointer.Y)
  232.     END MarkedViewer;
  233.     PROCEDURE PassFocus* (V: Viewers.Viewer);
  234.         VAR M: ControlMsg;
  235.     BEGIN M.id := defocus; FocusViewer.handle(FocusViewer, M); FocusViewer := V
  236.     END PassFocus;
  237.     (*command interpretation*)
  238.     PROCEDURE Call* (name: ARRAY OF CHAR; par: ParList; new: BOOLEAN; VAR res: INTEGER);
  239.         VAR Mod: Modules.Module; P: Modules.Command; i, j: INTEGER;
  240.     BEGIN
  241.         (*Amiga.Turbo; (* set task priority high *)*)     (*<<RD only MainLoop should change the Pri*)
  242.         res := 1;
  243.         i := 0; j := 0;
  244.         WHILE name[j] # 0X DO
  245.             IF name[j] = "." THEN i := j END;
  246.             INC(j)
  247.         END;
  248.         IF i > 0 THEN
  249.             name[i] := 0X;
  250.             IF new THEN Modules.Free(name, FALSE) END;
  251.             Mod := Modules.ThisMod(name);
  252.             IF Modules.res = 0 THEN
  253.                 INC(i); j := i;
  254.                 WHILE name[j] # 0X DO name[j - i] := name[j]; INC(j) END;
  255.                 name[j - i] := 0X;
  256.                 P := Modules.ThisCommand(Mod, name);
  257.                 IF Modules.res = 0 THEN
  258.                     Par := par; Par.vwr := Viewers.This(par.frame.X, par.frame.Y); P; res := 0
  259.                 ELSE
  260.                     res:=Modules.res
  261.                 END
  262.             ELSE res := Modules.res
  263.             END
  264.         END;
  265.         (*Amiga.Idle  (* set task priority low *)*)     (*<<RD only MainLoop should change the Pri*)
  266.     END Call;
  267.     PROCEDURE GetSelection* (VAR text: Texts.Text; VAR beg, end, time: LONGINT);
  268.         VAR M: SelectionMsg;
  269.     BEGIN
  270.         M.time := -1; Viewers.Broadcast(M); time := M.time;
  271.         IF time >= 0 THEN text := M.text; beg := M.beg; end := M.end END
  272.     END GetSelection;
  273.     PROCEDURE GC;
  274.     BEGIN
  275.         IF ActCnt<=0 THEN
  276.             Kernel.GC(TRUE);
  277.             ActCnt:=BasicCycle
  278.         END
  279.     END GC;
  280.     PROCEDURE Install* (T: Task);
  281.         VAR t: Task;
  282.     BEGIN t := PrevTask;
  283.         WHILE (t.next # PrevTask) & (t.next # T) DO t := t.next END;
  284.         IF t.next # T THEN T.next := PrevTask; t.next := T END
  285.     END Install;
  286.     PROCEDURE Remove* (T: Task);
  287.         VAR t: Task;
  288.     BEGIN t := PrevTask;
  289.         WHILE (t.next # T) & (t.next # PrevTask) DO t := t.next END;
  290.         IF t.next = T THEN t.next := t.next.next; PrevTask := t.next END;
  291.         IF CurTask = T THEN CurTask := PrevTask.next END
  292.     END Remove;
  293.     PROCEDURE Collect* (count: INTEGER);
  294.     BEGIN
  295.         ActCnt := count
  296.     END Collect;
  297.     PROCEDURE SetFont* (fnt: Fonts.Font);
  298.     BEGIN
  299.         CurFnt := fnt
  300.     END SetFont;
  301.     PROCEDURE SetColor* (col: SHORTINT);
  302.     BEGIN CurCol := col
  303.     END SetColor;
  304.     PROCEDURE SetOffset* (voff: SHORTINT);
  305.     BEGIN CurOff := voff
  306.     END SetOffset;
  307.     PROCEDURE NotifyTasks;    (* << JT *)
  308.         Call handler of all those task, which have set their time field to -1.
  309.         VAR t0, t1: Task;
  310.     BEGIN t0 := PrevTask;
  311.         REPEAT
  312.             CurTask := PrevTask.next;
  313.             IF CurTask.time = -1 THEN
  314.                 IF ~CurTask.safe THEN PrevTask.next := CurTask.next END;
  315.                 t1 := CurTask; CurTask.handle; PrevTask.next := CurTask;
  316.                 IF CurTask # t1 THEN RETURN END (*detect Remove(CurTask)*)
  317.             END;
  318.             PrevTask := CurTask
  319.         UNTIL CurTask = t0
  320.     END NotifyTasks;
  321.     PROCEDURE NotifyAllTasks;    (* << RD for Time depending MainLoop *)
  322.         Call handler of all those task, which have set their time field to -1.
  323.         VAR t0, t1: Task; ti: LONGINT;
  324.     BEGIN 
  325.         t0 := PrevTask;
  326.         ti:=Input.Time();
  327.         REPEAT
  328.             CurTask := PrevTask.next;
  329.             IF (CurTask.time <= ti) & (CurTask.time # -1) THEN
  330.                 IF ~CurTask.safe THEN PrevTask.next := CurTask.next END;
  331.                 t1 := CurTask; CurTask.handle; PrevTask.next := CurTask;
  332.                 IF CurTask # t1 THEN RETURN END (*detect Remove(CurTask)*)
  333.             END;
  334.             PrevTask := CurTask
  335.         UNTIL CurTask = t0
  336.     END NotifyAllTasks;
  337.     PROCEDURE Loop*;
  338.         The Oberon loop. The "task scheduler" of Oberon.
  339.         VAR
  340.             frame:RECORD END;
  341.             V: Viewers.Viewer; M: InputMsg; N: ControlMsg;
  342.             prevX, prevY, X, Y: INTEGER; keys: SET; ch: CHAR;
  343.             VM: Viewers.ViewerMsg;    (* << *)
  344.             LastLoopType: BOOLEAN;   (* <> *)
  345.         PROCEDURE HandleChar();    (*<RD*)
  346.             VAR
  347.                 chint: INTEGER;
  348.                 dumMod: Modules.Module;
  349.         BEGIN
  350.             Input.Read(ch);
  351.             chint:=ORD(ch);
  352.             IF ch = ESC THEN
  353.                 N.id := neutralize; Viewers.Broadcast(N); FadeCursor(Pointer)
  354.             ELSIF ch = SETUP THEN
  355.                 N.id := mark; N.X := X; N.Y := Y; V := Viewers.This(X, Y); V.handle(V, N)
  356.             ELSIF ch = 0CX THEN    (* << Form Feed => refresh display*)
  357.                 N.id := neutralize; Viewers.Broadcast(N); FadeCursor(Pointer);
  358.                 VM.id := Viewers.suspend; Viewers.Broadcast(VM);
  359.                 VM.id := Viewers.restore; Viewers.Broadcast(VM)
  360.             ELSIF (chint>245) & (chint<255) THEN    (*<RD  F6-F10, HELP and Clipboard-Keys *)
  361.                 IF (chint>251) & (Kernel.FKey[13]=NIL) THEN dumMod:=Modules.ThisMod("Clipboard") END;
  362.                 IF Kernel.FKey[chint-240]#NIL THEN Kernel.FKey[chint-240] END;
  363.             ELSE
  364.                 M.id := consume; M.ch := ch; M.fnt := CurFnt; M.col := CurCol; M.voff := CurOff;
  365.                 FocusViewer.handle(FocusViewer, M);
  366.                 DEC(ActCnt); NotifyTasks
  367.             END
  368.         END HandleChar;
  369.     BEGIN
  370.             Remember the current stack, so that the Kernel's stack collector knows where to look for pointers.
  371.         LastLoopType:=~Amiga.MainLoopType;            (* <> *)
  372.         Kernel.stackBottom := SYSTEM.ADR(frame);    (* << *)
  373.         prevX:=-1; prevY:=1;
  374.         LOOP
  375.             Input.Mouse(keys, X, Y);
  376.             IF Amiga.MainLoopType THEN (* Time depending MainLoop *)
  377.                 IF ~LastLoopType THEN Amiga.Turbo; LastLoopType:=TRUE END;
  378.                 IF Input.Available() > 0 THEN
  379.                     (*
  380.                         Handle all special characters, before handling the standard case.
  381.                     *)
  382.                     HandleChar();    (*<RD*)
  383.                 ELSIF keys # {} THEN
  384.                     (*
  385.                         As long, as a mouse key is pressed, send messages to the viewer on which the cursor
  386.                         is placed. Return to the loop only, when all mouse keys have been released.
  387.                     *)
  388.                     M.id := track; M.X := X; M.Y := Y; M.keys := keys;
  389.                     REPEAT
  390.                         V := Viewers.This(M.X, M.Y); V.handle(V, M);
  391.                         Input.Mouse(M.keys, M.X, M.Y)
  392.                     UNTIL M.keys = {};
  393.                     DEC(ActCnt); NotifyTasks
  394.                 ELSIF V24.Available() > 0 THEN
  395.                     (*
  396.                         Char available at the Serial Device => It is an event => notify ALL tasks
  397.                     *)
  398.                     NotifyTasks
  399.                 ELSE
  400.                     (*
  401.                         On mouse coordinate change notify the viewer below the actual mouse position.
  402.                     *)
  403.                     IF (X # prevX) OR (Y # prevY) OR ~Mouse.on THEN
  404.                         M.id := track; M.X := X; M.Y := Y; M.keys := {}; V := Viewers.This(X, Y);
  405.                         V.handle(V, M);
  406.                         prevX := X; prevY := Y
  407.                     END;
  408.                     (*
  409.                         Call handler of background task with a time not in the future and advance task pointer to next ready task.
  410.                         Tasks which are called by NotifiyTask (time=-1) are not called here.
  411.                     *)
  412.                     NotifyAllTasks
  413.                 END;
  414.                 Amiga.WaitTime(0, Amiga.TicsToWait); (* Wait for a while *)    
  415.             ELSE (* ever running MainLoop, low Task-Pri *)
  416.                     (* This is the way nearer the original *)
  417.                 IF LastLoopType THEN Amiga.Idle; LastLoopType:=FALSE END;
  418.                 IF Input.Available() > 0 THEN
  419.                     (*
  420.                         Handle all special characters, before handling the standard case.
  421.                     *)
  422.                     Amiga.Turbo;
  423.                     HandleChar();    (*<RD*)
  424.                     Amiga.Idle
  425.                 ELSIF keys # {} THEN
  426.                     (*
  427.                         As long, as a mouse key is pressed, send messages to the viewer on which the cursor
  428.                         is placed. Return to the loop only, when all mouse keys have been released.
  429.                     *)
  430.                     Amiga.Turbo;
  431.                     M.id := track; M.X := X; M.Y := Y; M.keys := keys;
  432.                     REPEAT
  433.                         V := Viewers.This(M.X, M.Y); V.handle(V, M);
  434.                         Input.Mouse(M.keys, M.X, M.Y)
  435.                     UNTIL M.keys = {};
  436.                     DEC(ActCnt); NotifyTasks;
  437.                     Amiga.Idle
  438.                 ELSIF V24.Available() > 0 THEN
  439.                     (*
  440.                         Char available at the Serial Device => It is an event => notify ALL tasks
  441.                     *)
  442.                     NotifyTasks
  443.                 ELSE
  444.                     (*
  445.                         On mouse coordinate change notify the viewer below the actual mouse position.
  446.                     *)
  447.                     IF (X # prevX) OR (Y # prevY) OR ~Mouse.on THEN
  448.                         Amiga.Turbo;
  449.                         M.id := track; M.X := X; M.Y := Y; M.keys := {}; V := Viewers.This(X, Y);
  450.                         V.handle(V, M);
  451.                         prevX := X; prevY := Y;
  452.                         Amiga.Idle
  453.                     END;
  454.                     (*
  455.                         Call handler of background task with a time not in the future and advance task pointer to next ready task.
  456.                         Tasks which are called by NotifiyTask (time=-1) are not called here.
  457.                     *)
  458.                     CurTask := PrevTask.next;
  459.                     IF (CurTask.time <= Input.Time()) & (CurTask.time # -1) THEN
  460.                         IF ~CurTask.safe THEN PrevTask.next := CurTask.next END;
  461.                         CurTask.handle; PrevTask.next := CurTask
  462.                     END;
  463.                     PrevTask := CurTask
  464.                 END
  465.             END
  466.         END
  467.     END Loop;
  468.     PROCEDURE Init;
  469.     BEGIN
  470.         User[0] := 0X;
  471.         Arrow.Fade := FlipArrow; Arrow.Draw := FlipArrow;
  472.         Star.Fade := FlipStar; Star.Draw := FlipStar;
  473.         OpenCursor(Mouse); OpenCursor(Pointer);
  474.         DW := Display.Width; DH := Display.Height; CL := Display.ColLeft;
  475.         H3 := DH - DH DIV 3;
  476.         H2 := H3 - H3 DIV 2;
  477.         H1 := DH DIV 5;
  478.         H0 := DH DIV 10;
  479.         unitW := DW DIV 8;
  480.         OpenDisplay(unitW * 5, unitW * 3, DH);
  481.         FocusViewer := Viewers.This(0, 0);
  482.         CurFnt := Fonts.Default;
  483.         CurCol := Display.white;
  484.         CurOff := 0;
  485.         Collect(BasicCycle);
  486.         NEW(PrevTask);
  487.         PrevTask.handle := GC;
  488.         PrevTask.safe := TRUE;
  489.         PrevTask.time := -1;    (* << (instead of 0) JT *)
  490.         PrevTask.next := PrevTask;
  491.         Display.SetMode(0, {})
  492.     END Init;
  493. BEGIN Init;
  494.     (* only if System not in boot file: *)
  495.     Mod:=Modules.ThisMod("System")
  496. END Oberon.
  497.